home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
aijournl
/
1987_03
/
exprt3.mar
< prev
next >
Wrap
Lisp/Scheme
|
1987-02-21
|
4KB
|
107 lines
; M I S S I O N A R I E S A N D C A N N I B A L S
;
; The following routines, when used in conjunction with the state-space
; search procedure, solve the missionaries and cannibals problem. Three
; missionaries and 3 cannibals are located on the right bank of a river,
; along with a two-man rowboat. We must find a way of moving all the
; missionaries and cannibals to the left bank. However, if at any time
; there are more cannibals than missionaries on a bank, the cannibals will
; exhibit a consuming interest in the misssionaries; this must be avoided.
;
; Each state is represented by an atom with the following properties:
; position -- a list of three elements,
; the number of missionaries on the right bank
; the number of cannibals on the right bank
; the position of the boat (left or right)
; g -- the estimated g for that state
; h -- the estimated h (value of function heuristic)
; parent -- the preceding state on the path from the initial state
; (the preceding state which gives rise to the least g,
; if there are several)
(defun initial-state ()
; return the initial state
(build-state 3 3 'right 0 nil))
(defun successors (state)
; returns the successors of state
; note that procedure try uses state and new-g, and modifies suc
(prog (m c boat new-g suc)
; extract parameters of current position and put in m, c, and boat
(setq m (car (get state 'position)))
(setq c (cadr (get state 'position)))
(setq boat (caddr (get state 'position)))
; g of new state = g of old state + 1 (all crossings are unit cost)
(setq new-g (+ 1 (get state 'g)))
(cond ((equal boat 'right)
(try (- m 2) c 'left new-g)
(try (- m 1) c 'left new-g)
(try (- m 1) (- c 1) 'left new-g)
(try m (- c 1) 'left new-g)
(try m (- c 2) 'left new-g))
(t ; boat is on left
(try (+ m 2) c 'right)
(try (+ m 1) c 'right)
(try (+ m 1) (+ c 1) 'right)
(try m (+ c 1) 'right)
(try m (+ c 2) 'right)))
(return suc)))
(defun try (new-m new-c new-boat new-g)
; if position(new-m,new-c,new-boat) is valid, add new state to suc
(cond ((valid new-m new-c)
(setq suc (cons (build-state new-m new-c new-boat new-g state)
suc)))))
(defun valid (miss cann)
; returns true if having 'miss' missionaries and 'cann' cannibals
; on the right bank is a valid state
(and (>= miss 0)
(>= cann 0)
(< miss 4)
(< cann 4)
(or (zerop miss) (>= miss cann))
(or (zerop (- 3 miss)) (>= (- 3 miss) (- 3 cann)))))
(defun build-state (miss cann boat g parent)
; creates a new state with parameters as specified by argument list
(prog (newstate)
(setq newstate (gensym))
(putprop newstate (list miss cann boat) 'position)
(putprop newstate g 'g)
(putprop newstate (heuristic miss cann boat) 'h)
(putprop newstate parent 'parent)
(return newstate)))
(defun heuristic (miss cann boat)
; our heuristic (h) function
(cond ((equal boat 'left)
(* 2 (+ miss cann)))
(t ; boat is on right
(* 2 (max 0 (+ miss cann -2))))))
(defun goal (state)
; returns true if state is a goal state (no missionaries or cannibals on right)
(and (zerop (car (get state 'position)))
(zerop (cadr (get state 'position)))))
(defun print-solution (state)
; invoked by search algorithm with goal state,
; prints sequence of states from initial state to goal.
(cond ((null state)
(print 'solution:))
(t
(print-solution (get state 'parent))
(print (get state 'position))
))
)
(defun trace (comment state)
; if trace-switch is true, print out comment and position
; associated with state
(cond
(trace-switch
(print `(,comment state ,state with position ,(get state 'position)
h(x) = ,(get state 'h))))))